package com.yohann.boot.util;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;

import java.net.InetAddress;

/**
 * @author Yeung Wah
 * @since 2021/9/2
 */
@Slf4j
public class LogUtils {

    private LogUtils() {
    }

    @SneakyThrows
    public static void applicationLog(ConfigurableApplicationContext application) {
        Environment env = application.getEnvironment();
        String ip = InetAddress.getLocalHost().getHostAddress();
        String port = env.getProperty("server.port");
        String applicationName = env.getProperty("spring.application.name", "");
        log.info("\n_______________________________________________________\n\t" +
                "Application " + applicationName + " is running! \n\t" +
                "Doc: \t\thttp://" + ip + ":" + port + "/doc.html\n\t" +
                "Doc: \t\thttp://127.0.0.1:" + port + "/doc.html\n" +
                "_______________________________________________________");
    }

    /**
     * DEBUG等级日志打印
     *
     * @param debug debug
     */
    public static void debug(String debug) {
        log.info(String.format("[DEBUG:%s]", debug));
        printStackTrace();
    }

    /**
     * INFO等级日志打印
     *
     * @param info info
     */
    public static void info(String info) {
        log.info(String.format("[INFO:%s]", info));
        printStackTrace();
    }

    /**
     * WARN等级日志打印
     *
     * @param warn warn
     */
    public static void warn(String warn) {
        log.info(String.format("[WARN:%s]", warn));
        printStackTrace();
    }

    /**
     * ERROR等级日志打印
     *
     * @param error error
     */
    public static void error(String error) {
        log.info(String.format("[ERROR:%s]", error));
        printStackTrace();
    }

    /**
     * 打印日志栈追踪（5层）
     */
    private static void printStackTrace() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (int i = 3; i < stackTrace.length && i < 8; i++) {
            StackTraceElement element = stackTrace[i];
            String stackTraceStr = getStackTraceStr(element);
            log.info(String.format("[StackTrace:%s]", stackTraceStr));
        }
    }

    /**
     * 获取方法栈元素信息
     */
    public static String getStackTraceStr(StackTraceElement element) {
        String className = element.getClassName();
        String methodName = element.getMethodName();
        String fileName = element.getFileName();
        int lineNumber = element.getLineNumber();
        return String.format("%s.%s(%s:%d)", className, methodName, fileName, lineNumber);
    }

    /**
     * DEBUG等级日志打印
     *
     * @param throwable 异常
     */
    public static void debug(Throwable throwable) {
        log.info(String.format("[DEBUG:%s]", throwable.getMessage()), throwable);
    }

    /**
     * INFO等级日志打印
     *
     * @param throwable 异常
     */
    public static void info(Throwable throwable) {
        log.info(String.format("[INFO:%s]", throwable.getMessage()), throwable);
    }

    /**
     * WARN等级日志打印
     *
     * @param throwable 异常
     */
    public static void warn(Throwable throwable) {
        log.info(String.format("[WARN:%s]", throwable.getMessage()), throwable);
    }

    /**
     * ERROR等级日志打印
     *
     * @param throwable 异常
     */
    public static void error(Throwable throwable) {
        log.info(String.format("[ERROR:%s]", throwable.getMessage()), throwable);
    }

    /**
     * INFO等级日志打印
     *
     * @param debug     debug
     * @param throwable 异常
     */
    public static void debug(String debug, Throwable throwable) {
        log.info(String.format("[DEBUG:%s]", debug), throwable);
    }

    /**
     * INFO等级日志打印
     *
     * @param info      info
     * @param throwable 异常
     */
    public static void info(String info, Throwable throwable) {
        log.info(String.format("[INFO:%s]", info), throwable);
    }

    /**
     * WARN等级日志打印
     *
     * @param warn      info
     * @param throwable 异常
     */
    public static void warn(String warn, Throwable throwable) {
        log.info(String.format("[WARN:%s]", warn), throwable);
    }

    /**
     * ERROR等级日志打印
     *
     * @param error     error
     * @param throwable 异常
     */
    public static void error(String error, Throwable throwable) {
        log.info(String.format("[ERROR:%s]", error), throwable);
    }

}